﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;

namespace Tomahawk.Runtime.CrashDump
{
#if XBOX
    public sealed class CrashDebugGame
    {
        private bool exit = false;
        private SpriteFont font = null;
        private SpriteBatch spriteBatch = null;
        private readonly Exception exception = null;
        private GraphicsDevice graphicsDevice = null;
        private ContentManager contentManager = null;

        public CrashDebugGame(Exception exception, GraphicsDevice graphicsDevice, ContentManager contentManager)
        {
            this.exception = exception;
            this.graphicsDevice = graphicsDevice;
            this.contentManager = contentManager;

            font = this.contentManager.Load<SpriteFont>(@"Tomahawk.Content\Debug\DebugWriter");
            spriteBatch = new SpriteBatch(this.graphicsDevice);
        }

        public void Run()
        {
            while (!exit)
            {
                Update();
                Draw();
            }
        }

        private void Update()
        {
            exit = (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
                Keyboard.GetState().IsKeyDown(Keys.Escape));
        }

        private void Draw()
        {
            graphicsDevice.Clear(Color.DarkBlue);

            int line = 2;
            float fontScale = 2.0f;

            spriteBatch.Begin();
            
            spriteBatch.DrawString(
               font,
               "**** CRASH LOG ****",
               new Vector2(20f, line * fontScale * font.LineSpacing),
               Color.White,
               0.0f,
               Vector2.Zero,
               fontScale,
               SpriteEffects.None,
               0.0f);
            line++;

            spriteBatch.DrawString(
               font,
               "Press Back to Exit",
               new Vector2(20f, line * fontScale * font.LineSpacing),
               Color.White,
               0.0f,
               Vector2.Zero,
               fontScale,
               SpriteEffects.None,
               0.0f);
            line++;

            string exceptionMessage = string.Format("Exception: {0}", exception.Message);
            List<string> exceptionMessageLines = WrapLine(exceptionMessage, 100);

            foreach (string text in exceptionMessageLines)
            {
                spriteBatch.DrawString(
                   font,
                   text,
                   new Vector2(20f, line * fontScale * font.LineSpacing),
                   Color.White,
                   0.0f,
                   Vector2.Zero,
                   fontScale,
                   SpriteEffects.None,
                   0.0f);
                line++;
            }

            string stackTrace = string.Format("Stack Trace:\n{0}", exception.StackTrace);
            List<string> stackTraceLines = WrapLine(stackTrace, 100);
            foreach (string text in stackTraceLines)
            {
                spriteBatch.DrawString(
                   font,
                   text,
                   new Vector2(20f, line * fontScale * font.LineSpacing),
                   Color.White,
                   0.0f,
                   Vector2.Zero,
                   fontScale,
                   SpriteEffects.None,
                   0.0f);
                line++;
            }
            
            spriteBatch.End();

            graphicsDevice.Present();
        }

        private List<string> WrapLine(string line, int columns)
        {
            List<string> wraplines = new List<string>();
            if (line.Length > 0)
            {
                wraplines.Add("");
                int lineNum = 0;

                for (int i = 0; i < line.Length; i++)
                {
                    string ch = line.Substring(i, 1);

                    if (ch == "\n" || wraplines[lineNum].Length > columns)
                    {
                        wraplines.Add("");
                        lineNum++;
                    }
                    else
                    {
                        wraplines[lineNum] += ch;
                    }
                }
            }

            return wraplines;
        }
    }
#endif
}
